home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / devices / msh_1_5 / part05 < prev    next >
Text File  |  1990-02-21  |  29KB  |  1,115 lines

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i083: MSH 1.5 - Messydos File System Handler , Part05/06
  5. Message-ID: <11502@xanth.cs.odu.edu>
  6. Date: 21 Feb 90 02:01:54 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: Olaf 'Rhialto' Seibert <U211344%HNYKUN11.BITNET@CUNYVM.CUNY.EDU>
  9. Lines: 1101
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11. X-Mail-Submissions-To: Amiga@cs.odu.edu
  12. X-Post-Discussions-To: comp.sys.amiga
  13.  
  14. Submitted-by: Olaf 'Rhialto' Seibert <U211344%HNYKUN11.BITNET@CUNYVM.CUNY.EDU>
  15. Posting-number: Volume 90, Issue 083
  16. Archive-name: devices/msh-1.5/part05
  17.  
  18. #!/bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 5 (of 6)."
  25. # Contents:  src/pack.c
  26. # Wrapped by tadguy@xanth on Tue Feb 20 20:57:13 1990
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'src/pack.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'src/pack.c'\"
  30. else
  31. echo shar: Extracting \"'src/pack.c'\" \(26316 characters\)
  32. sed "s/^X//" >'src/pack.c' <<'END_OF_FILE'
  33. X/*-
  34. X * $Id: pack.c,v 1.3 90/02/03 17:02:05 Rhialto Exp $
  35. X * $Log:    pack.c,v $
  36. X * Revision 1.3  90/02/03  17:02:05  Rhialto
  37. X * Add error checking wrt dosalloc()
  38. X * 
  39. X * Revision 1.2  89/12/17  23:06:54  Rhialto
  40. X * Add ACTION_SET_PROTECT
  41. X *
  42. X * Revision 1.1  89/12/17  19:53:24  Rhialto
  43. X * Initial revision
  44. X *
  45. X *
  46. X *  Originally:
  47. X *
  48. X *    DOSDEVICE.C        V1.10   2 November 1987
  49. X *
  50. X *    EXAMPLE DOS DEVICE DRIVER FOR AZTEC.C    PUBLIC DOMAIN.
  51. X *
  52. X *    By Matthew Dillon.
  53. X *
  54. X *  This has been stripped and refilled with messydos code
  55. X *  by Olaf Seibert.
  56. X *
  57. X *  This code is (C) Copyright 1989 by Olaf Seibert. All rights reserved. May
  58. X *  not be used or copied without a licence.
  59. X *
  60. X *  Please note that we are NOT pure, so if you wish to mount
  61. X *  multiple MSDOS units, you must use different copies of this driver.
  62. X *
  63. X *  This file forms the interface between the actual handler code and all
  64. X *  AmigaDOS requirements. It shields it from ugly stuff like BPTRs, BSTRs,
  65. X *  FileLocks, FileHandles and VolumeNodes (in the form of DeviceLists).
  66. X *  Also, most protection against non-inserted disks is done here.
  67. X-*/
  68. X
  69. X#include "dos.h"
  70. X#include "han.h"
  71. X
  72. X#ifdef DEBUG
  73. X#   define    debug(x)  dbprintf x
  74. X#else
  75. X#   define    debug(x)
  76. X#endif
  77. X
  78. X/*
  79. X * Since this code might be called several times in a row without being
  80. X * unloaded, you CANNOT ASSUME GLOBALS HAVE BEEN ZERO'D!!  This also goes
  81. X * for any global/static assignments that might be changed by running the
  82. X * code.
  83. X */
  84. X
  85. XPORT           *DosPort;    /* Our DOS port... */
  86. XDEVNODE        *DevNode;    /* Our DOS node.. created by DOS for us */
  87. XDEVLIST        *VolNode;    /* Device List structure for our volume
  88. X                 * node */
  89. X
  90. Xvoid           *SysBase;    /* EXEC library base */
  91. XDOSLIB           *DOSBase;    /* DOS library base for debug process */
  92. Xlong        PortMask;    /* The signal mask for our DosPort */
  93. Xlong        WaitMask;    /* The signal mask to wait for */
  94. Xshort        DiskChanged;    /* Set by disk change interrupt */
  95. Xshort        Inhibited;    /* Are we inhibited (ACTION_INHIBIT)? */
  96. Xlong        UnitNr;     /* From */
  97. Xchar           *DevName;    /*   the */
  98. Xulong        DevFlags;    /*     mountlist */
  99. XPACKET           *DosPacket;    /* For the SystemRequest pr_WindowPtr */
  100. X
  101. Xvoid ChangeIntHand(), DiskChange();
  102. Xvoid NewVolNodeName(), NewVolNodeDate();
  103. X
  104. Xstruct Interrupt ChangeInt = {
  105. X    { 0 },            /* is_Node */
  106. X    0,                /* is_Data */
  107. X    ChangeIntHand,        /* is_Code */
  108. X};
  109. X
  110. X/*
  111. X * Don't call the entry point main().  This way, if you make a mistake
  112. X * with the compile options you'll get a link error.
  113. X */
  114. X
  115. Xvoid
  116. Xmessydoshandler()
  117. X{
  118. X    register PACKET *packet;
  119. X    MSG        *msg;
  120. X    byte        notdone;
  121. X    long        OpenCount;        /* How many open files/locks there are */
  122. X
  123. X    /*
  124. X     * Initialize all global variables.  SysBase MUST be initialized
  125. X     * before we can make Exec calls.  AbsExecBase is a library symbol
  126. X     * referencing absolute memory location 4.
  127. X     */
  128. X
  129. X    SysBase = AbsExecBase;
  130. X    DOSBase = OpenLibrary("dos.library", 0L);
  131. X
  132. X#ifdef DEBUG
  133. X    /*
  134. X     * Initialize debugging code as soon as possible. Only SysBase and
  135. X     * DOSBase are required.
  136. X     */
  137. X
  138. X    dbinit();
  139. X#endif                /* DEBUG */
  140. X
  141. X    DosPort = &((struct Process *)FindTask(NULL))->pr_MsgPort;
  142. X
  143. X    WaitPort(DosPort);      /* Get Startup Packet  */
  144. X    msg = GetMsg(DosPort);
  145. X    packet = (PACKET *) msg->mn_Node.ln_Name;
  146. X
  147. X
  148. X    DevNode = BTOC(PArg3);
  149. X    {
  150. X    struct FileSysStartupMsg *fssm;
  151. X    ulong *environ;
  152. X
  153. X    DevName = "messydisk.device";
  154. X    UnitNr = 0;
  155. X    DevFlags = 0;
  156. X
  157. X    MaxCache = 5;
  158. X    BufMemType = MEMF_PUBLIC;
  159. X    Disk.nsides = MS_NSIDES;
  160. X    Disk.spt = MS_SPT;
  161. X    Disk.bps = MS_BPS;
  162. X    Disk.lowcyl = 0;
  163. X
  164. X    if (fssm = (struct FileSysStartupMsg *)BTOC(DevNode->dn_Startup)) {
  165. X                    /* Same as BTOC(packet->dp_Arg2) */
  166. X        UnitNr = fssm->fssm_Unit;
  167. X        if (fssm->fssm_Device)
  168. X        DevName = (char *)BTOC(fssm->fssm_Device)+1;
  169. X        DevFlags = fssm->fssm_Flags;
  170. X
  171. X        if (environ = BTOC(fssm->fssm_Environ)) {
  172. X        debug(("environ size %ld\n", environ[0]));
  173. X#define get(xx,yy)  if (environ[0] >= yy) xx = environ[yy];
  174. X
  175. X        get(MaxCache, DE_NUMBUFFERS);
  176. X        get(BufMemType, DE_MEMBUFTYPE);
  177. X        get(Disk.nsides, DE_NUMHEADS);
  178. X        get(Disk.spt, DE_BLKSPERTRACK);
  179. X        get(Disk.bps, DE_SIZEBLOCK);
  180. X        Disk.bps *= 4;
  181. X        debug(("Disk.bps %d\n", Disk.bps));
  182. X        get(Disk.lowcyl, DE_LOWCYL);
  183. X#undef get
  184. X        }
  185. X    }
  186. X    Disk.lowcyl *= (long)MS_BPS * Disk.spt * Disk.nsides;
  187. X    }
  188. X
  189. X    if (DOSBase && HanOpenUp()) {
  190. X    /*
  191. X     * Loading DevNode->dn_Task causes DOS *NOT* to startup a new
  192. X     * instance of the device driver for every reference.    E.G. if
  193. X     * you were writing a CON: device you would want this field to be
  194. X     * NULL.
  195. X     */
  196. X
  197. X    DevNode->dn_Task = DosPort;
  198. X
  199. X    PRes1 = DOSTRUE;
  200. X    PRes2 = 0;
  201. X    } else {            /* couldn't open dos.library  */
  202. X    PRes1 = DOSFALSE;
  203. X    PRes2 = ERROR_NO_FREE_STORE;    /* no better message available */
  204. X    returnpacket(packet);
  205. X    goto exit;        /* exit process    */
  206. X    }
  207. X    returnpacket(packet);
  208. X
  209. X    /* Initialize some more global variables    */
  210. X
  211. X    PortMask = 1L << DosPort->mp_SigBit;
  212. X    VolNode = NULL;
  213. X    OpenCount = 0;
  214. X    Inhibited = 0;
  215. X
  216. X    /* Get the first real packet       */
  217. X    WaitPort(DosPort);
  218. X    msg = GetMsg(DosPort);
  219. X    notdone = 1;
  220. X    WaitMask = PortMask | (1L << DiskReplyPort->mp_SigBit);
  221. X    TDAddChangeInt(&ChangeInt);
  222. X    DiskInserted(WhichDiskInserted());
  223. X
  224. X    goto entry;
  225. X
  226. X    /*
  227. X     * Here begins the endless loop, waiting for requests over our message
  228. X     * port and executing them.  Since requests are sent over the message
  229. X     * port in our device and volume nodes, we must not use our Process
  230. X     * message port for this: this precludes being able to call DOS
  231. X     * functions ourselves.
  232. X     */
  233. X
  234. Xtop:
  235. X    for (notdone = 1; notdone;) {
  236. X    Wait(WaitMask);
  237. X    if (DiskChanged)
  238. X        DiskChange();
  239. X    while (msg = GetMsg(DosPort)) {
  240. X        byte        buf[256];    /* Max length of BCPL strings is
  241. X                     * 255 + 1 for \0. */
  242. X
  243. X    entry:
  244. X        if (DiskChanged)
  245. X        DiskChange();
  246. X        packet = (PACKET *) msg->mn_Node.ln_Name;
  247. X        PRes1 = DOSFALSE;
  248. X        PRes2 = 0;
  249. X        error = 0;
  250. X        debug(("Packet: %3ld %08lx %08lx %08lx %10s\n",
  251. X             PType, PArg1, PArg2, PArg3, typetostr(PType)));
  252. X
  253. X        DosPacket = packet;     /* For the System Requesters */
  254. X        switch (PType) {
  255. X        case ACTION_DIE:        /* attempt to die?  */
  256. X        notdone = 0;        /* try to die     */
  257. X        break;
  258. X        case ACTION_CURRENT_VOLUME: /* -              VolNode,UnitNr */
  259. X        PRes1 = (long) CTOB(VolNode);
  260. X        PRes2 = UnitNr;
  261. X        break;
  262. X        case ACTION_LOCATE_OBJECT:    /* Lock,Name,Mode    Lock         */
  263. X        {
  264. X            register struct FileLock *newlock;
  265. X            struct FileLock *lock;
  266. X            struct MSFileLock *msfl;
  267. X            long        lockmode;
  268. X
  269. X            lock = BTOC(PArg1);
  270. X            if (CheckRead(lock))
  271. X            break;
  272. X            btos(PArg2, buf);
  273. X            if ((lockmode = PArg3) != EXCLUSIVE_LOCK)
  274. X            lockmode = SHARED_LOCK;
  275. X            msfl = MSLock(lock ? lock->fl_Key : NULL,
  276. X                  buf,
  277. X                  lockmode);
  278. X            if (msfl) {
  279. X            if (newlock = NewFileLock(msfl, lock)) {
  280. X                newlock->fl_Access = lockmode;
  281. X                PRes1 = (long) CTOB(newlock);
  282. X                OpenCount++;
  283. X            } else
  284. X                MSUnLock(msfl);
  285. X            }
  286. X        }
  287. X        break;
  288. X        case ACTION_RENAME_DISK:    /* BSTR:NewName        Bool      */
  289. X        if (CheckWrite(NULL))
  290. X            break;
  291. X        btos(PArg1, buf);
  292. X        buf[31] = '\0';
  293. X        if (PRes1 = MSRelabel(buf))
  294. X            NewVolNodeName();
  295. X        break;
  296. X        case ACTION_FREE_LOCK:    /* Lock            Bool      */
  297. X        {
  298. X            struct FileLock *lock;
  299. X            struct MSFileLock *msfl;
  300. X
  301. X            PRes1 = DOSTRUE;
  302. X            lock = BTOC(PArg1);
  303. X            if (lock == NULL)
  304. X            break;
  305. X
  306. X            msfl = (struct MSFileLock *)lock->fl_Key;
  307. X            FreeFileLock(lock); /* may remove last lock on volume */
  308. X            MSUnLock(msfl);     /* may call MayFreeVolNode */
  309. X            OpenCount--;
  310. X        }
  311. X        break;
  312. X        case ACTION_DELETE_OBJECT:    /* Lock,Name        Bool         */
  313. X        {
  314. X            struct FileLock *lock;
  315. X
  316. X            lock = BTOC(PArg1);
  317. X            if (CheckWrite(lock))
  318. X            break;
  319. X            btos(PArg2, buf);
  320. X            PRes1 = MSDeleteFile(lock ? lock->fl_Key : NULL,
  321. X                     buf);
  322. X        }
  323. X        break;
  324. X        case ACTION_RENAME_OBJECT:    /* SLock,SName,DLock,DName   Bool    */
  325. X        {
  326. X            struct FileLock *slock, *dlock;
  327. X            char         buf2[256];
  328. X
  329. X            slock = BTOC(PArg1);
  330. X            dlock = BTOC(PArg3);
  331. X            if (CheckWrite(slock) || CheckWrite(dlock))
  332. X            break;
  333. X            btos(PArg2, buf);
  334. X            btos(PArg4, buf2);
  335. X            PRes1 = MSRename(slock ? slock->fl_Key : NULL,
  336. X                     buf,
  337. X                     dlock ? dlock->fl_Key : NULL,
  338. X                     buf2);
  339. X        }
  340. X        break;
  341. X        case ACTION_MORECACHE:    /* #BufsToAdd           Bool      */
  342. X        if ((MaxCache += (short) PArg1) <= 0) {
  343. X            MaxCache = 1;
  344. X        } else
  345. X            PRes1 = DOSTRUE;
  346. X        debug(("Now %d cache sectors\n", MaxCache));
  347. X        break;
  348. X        case ACTION_COPY_DIR:    /* Lock            Lock      */
  349. X        {
  350. X            register struct FileLock *newlock;
  351. X            struct FileLock *lock;
  352. X            struct MSFileLock *msfl;
  353. X
  354. X            lock = BTOC(PArg1);
  355. X
  356. X            msfl = MSDupLock(lock ? lock->fl_Key : NULL);
  357. X
  358. X            if (msfl) {
  359. X            if (newlock = NewFileLock(msfl, lock)) {
  360. X                newlock->fl_Access =
  361. X                lock ? lock->fl_Access : SHARED_LOCK;
  362. X                PRes1 = (long) CTOB(newlock);
  363. X                OpenCount++;
  364. X            } else
  365. X                MSUnLock(msfl);
  366. X            }
  367. X        }
  368. X        break;
  369. X        case ACTION_SET_PROTECT:    /* -,Lock,Name,Mask       Bool      */
  370. X        {
  371. X            struct FileLock *lock;
  372. X
  373. X            lock = BTOC(PArg2);
  374. X            if (CheckWrite(lock))
  375. X            break;
  376. X            btos(PArg3, buf);
  377. X            PRes1 = MSSetProtect(lock ? lock->fl_Key : NULL, buf, PArg4);
  378. X        }
  379. X        break;
  380. X        case ACTION_CREATE_DIR:    /* Lock,Name        Lock         */
  381. X        {
  382. X            register struct FileLock *newlock;
  383. X            struct FileLock *lock;
  384. X            struct MSFileLock *msfl;
  385. X
  386. X            lock = BTOC(PArg1);
  387. X            if (CheckWrite(lock))
  388. X            break;
  389. X            btos(PArg2, buf);
  390. X
  391. X            msfl = MSCreateDir(lock ? lock->fl_Key : NULL, buf);
  392. X
  393. X            if (msfl) {
  394. X            if (newlock = NewFileLock(msfl, lock)) {
  395. X                newlock->fl_Access = SHARED_LOCK;
  396. X                PRes1 = (long) CTOB(newlock);
  397. X                OpenCount++;
  398. X            } else
  399. X                MSUnLock(msfl);
  400. X            }
  401. X        }
  402. X        break;
  403. X        case ACTION_EXAMINE_OBJECT: /* Lock,Fib           Bool         */
  404. X        {
  405. X            struct FileLock *lock;
  406. X
  407. X            lock = BTOC(PArg1);
  408. X            if (CheckRead(lock))
  409. X            break;
  410. X            PRes1 = MSExamine(lock ? lock->fl_Key : NULL, BTOC(PArg2));
  411. X        }
  412. X        break;
  413. X        case ACTION_EXAMINE_NEXT:    /* Lock,Fib           Bool         */
  414. X        {
  415. X            struct FileLock *lock;
  416. X
  417. X            lock = BTOC(PArg1);
  418. X            if (CheckRead(lock))
  419. X            break;
  420. X            PRes1 = MSExNext(lock ? lock->fl_Key : NULL, BTOC(PArg2));
  421. X        }
  422. X        break;
  423. X        case ACTION_DISK_INFO:    /* InfoData           Bool:TRUE     */
  424. X        PRes1 = MSDiskInfo(BTOC(PArg1));
  425. X        break;
  426. X        case ACTION_INFO:    /* Lock,InfoData           Bool:TRUE     */
  427. X        if (CheckRead(BTOC(PArg1)))
  428. X            break;
  429. X        PRes1 = MSDiskInfo(BTOC(PArg2));
  430. X        break;
  431. X        case ACTION_FLUSH:        /* writeout bufs, disk motor off     */
  432. X        MSUpdate(1);
  433. X        break;
  434. X/*        case ACTION_SET_COMMENT:    /* -,Lock,Name,Comment       Bool      */
  435. X        case ACTION_PARENT: /* Lock                ParentLock    */
  436. X        {
  437. X            register struct FileLock *newlock;
  438. X            struct FileLock *lock;
  439. X            struct MSFileLock *msfl;
  440. X            long mode;
  441. X
  442. X            lock = BTOC(PArg1);
  443. X
  444. X            msfl = MSParentDir(lock ? lock->fl_Key : NULL);
  445. X
  446. X            if (msfl) {
  447. X            if (newlock = NewFileLock(msfl, lock)) {
  448. X                newlock->fl_Access = SHARED_LOCK;
  449. X                PRes1 = (long) CTOB(newlock);
  450. X                OpenCount++;
  451. X            } else
  452. X                MSUnLock(msfl);
  453. X            }
  454. X        }
  455. X        break;
  456. X        case ACTION_INHIBIT:    /* Bool            Bool      */
  457. X        if (Inhibited = PArg1) {
  458. X            DiskRemoved();
  459. X        } else { /* Fall through to ACTION_DISK_CHANGE: */
  460. X        case ACTION_DISK_CHANGE:    /* ?               ?         */
  461. X            DiskChange();
  462. X        }
  463. X        PRes1 = DOSTRUE;
  464. X        break;
  465. X        case ACTION_SET_DATE: /* -,Lock,Name,CPTRDateStamp       Bool      */
  466. X        {
  467. X            struct FileLock *lock;
  468. X
  469. X            lock = BTOC(PArg2);
  470. X            if (CheckWrite(lock))
  471. X            break;
  472. X            btos(PArg3, buf);
  473. X            PRes1 = MSSetDate(lock ? lock->fl_Key : NULL,
  474. X                      buf,
  475. X                      PArg4);
  476. X        }
  477. X        break;
  478. X        case ACTION_READ:    /* FHArg1,CPTRBuffer,Length      ActLength  */
  479. X        if (CheckRead(NULL)) {
  480. X            PRes1 = -1;
  481. X        } else
  482. X            PRes1 = MSRead(PArg1, PArg2, PArg3);
  483. X        break;
  484. X        case ACTION_WRITE:    /* FHArg1,CPTRBuffer,Length      ActLength  */
  485. X        if (CheckWrite(NULL)) {
  486. X            PRes1 = -1;
  487. X        } else
  488. X            PRes1 = MSWrite(PArg1, PArg2, PArg3);
  489. X        break;
  490. X        case ACTION_OPENNEW:    /* FileHandle,Lock,Name    Bool      */
  491. X        {
  492. X            struct MSFileHandle *msfh;
  493. X            struct FileHandle *fh;
  494. X            struct FileLock *lock;
  495. X
  496. X            if (CheckWrite(BTOC(PArg2)))
  497. X            break;
  498. X        case ACTION_OPENRW:     /* FileHandle,Lock,Name    Bool      */
  499. X        case ACTION_OPENOLD:    /* FileHandle,Lock,Name    Bool      */
  500. X
  501. X            fh = BTOC(PArg1);
  502. X            lock = BTOC(PArg2);
  503. X            if (CheckRead(lock))
  504. X            break;
  505. X            btos(PArg3, buf);
  506. X            debug(("'%s' ", buf));
  507. X            msfh = MSOpen(lock ? lock->fl_Key : NULL,
  508. X                  buf,
  509. X                  PType);
  510. X            if (msfh) {
  511. X            fh->fh_Arg1 = (long) msfh;
  512. X            PRes1 = DOSTRUE;
  513. X            OpenCount++;
  514. X            }
  515. X        }
  516. X        break;
  517. X        case ACTION_CLOSE:    /* FHArg1              Bool:TRUE  */
  518. X        MSClose(PArg1);
  519. X        PRes1 = DOSTRUE;
  520. X        OpenCount--;
  521. X        break;
  522. X        case ACTION_SEEK:    /* FHArg1,Position,Mode      OldPosition */
  523. X        if (CheckRead(NULL)) {
  524. X            PRes1 = -1;
  525. X        } else
  526. X            PRes1 = MSSeek(PArg1, PArg2, PArg3);
  527. X        break;
  528. X        /*
  529. X         * A few other packet types which we do not support
  530. X         */
  531. X/*        case ACTION_WAIT_CHAR:    /* Timeout, ticks       Bool      */
  532. X/*        case ACTION_RAWMODE:    /* Bool(-1:RAW 0:CON)      OldState  */
  533. X        default:
  534. X        error = ERROR_ACTION_NOT_KNOWN;
  535. X        break;
  536. X        } /* end switch */
  537. X        if (packet) {
  538. X        if (error) {
  539. X            debug(("ERR=%d\n", error));
  540. X            PRes2 = error;
  541. X        }
  542. X#ifdef DEBUG
  543. X        else {
  544. X            debug(("RES=%06lx\n", PRes1));
  545. X        }
  546. X#endif
  547. X        returnpacket(packet);
  548. X        DosPacket = NULL;
  549. X        }
  550. X#ifdef DEBUG
  551. X        else {
  552. X        debug(("NOREP\n"));
  553. X        }
  554. X#endif
  555. X    } /* end while (GetMsg()) */
  556. X
  557. X    /*
  558. X     *  Now check for an other cause of events: timer IO.
  559. X     *  Unfortunately we cannot be sure that we always get a signal
  560. X     *  when the timeout has elapsed, since the same message port is
  561. X     *  used for other IO.
  562. X     */
  563. X    if (CheckIO(TimeIOReq)) {   /* Timer finished? */
  564. X        debug(("TimeIOReq is finished\n"));
  565. X        if (DelayState != DELAY_OFF) {
  566. X        MSUpdate(0);    /* Also may switch off motor */
  567. X        }
  568. X    }
  569. X    } /* end for (;notdone) */
  570. X
  571. X#ifdef DEBUG
  572. X    debug(("Can we remove ourselves? "));
  573. X    Delay(50L);                 /* I wanna even see the debug message! */
  574. X#endif                /* DEBUG */
  575. X    Forbid();
  576. X    if (OpenCount || packetsqueued()) {
  577. X    Permit();
  578. X    debug((" ..  not yet!\n"));
  579. X    goto top;        /* sorry... can't exit     */
  580. X    }
  581. X    debug((" .. yes!\n"));
  582. X
  583. X    /*
  584. X     * Causes a new process to be created on next reference.
  585. X     */
  586. X
  587. X    DevNode->dn_Task = NULL;
  588. X    TDRemChangeInt();
  589. X    DiskRemoved();
  590. X    HanCloseDown();
  591. X    debug(("HanCloseDown returned. dbuninit in 2 seconds:\n"));
  592. X
  593. X    /*
  594. X     * Remove debug window, closedown, fall of the end of the world.
  595. X     */
  596. Xexit:
  597. X#ifdef DEBUG
  598. X    Delay(100L);                /* This is dangerous! */
  599. X    dbuninit();
  600. X#endif                /* DEBUG */
  601. X
  602. X#if 1
  603. X    UnLoadSeg(DevNode->dn_SegList);     /* This is real fun. We are still */
  604. X    DevNode->dn_SegList = NULL;     /* Forbid()den, fortunately */
  605. X#endif
  606. X
  607. X    CloseLibrary(DOSBase);
  608. X
  609. X    /* Fall off the end of the world. Implicit Permit(). */
  610. X}
  611. X
  612. Xvoid
  613. XChangeIntHand()
  614. X{
  615. X/* INDENT OFF */
  616. X#asm
  617. X    move.l  a6,-(sp)
  618. X#endasm
  619. X    DiskChanged = 1;
  620. X    Signal(DosPort->mp_SigTask, PortMask);
  621. X#asm
  622. X    move.l  (sp)+,a6
  623. X#endasm
  624. X/* INDENT ON */
  625. X}
  626. X
  627. X/*
  628. X *  Make a new struct FileLock, for DOS use. It is put on a singly linked
  629. X *  list, which is attached to the same VolumeNode the old lock was on.
  630. X *
  631. X *  Also note that we must ALWAYS be prepared to UnLock() or DupLock()
  632. X *  any FileLocks we ever made, even if the volume in question has been
  633. X *  removed and/or inserted into another drive with another FileSystem
  634. X *  handler!
  635. X *
  636. X * DOS makes certain assumptions about LOCKS.    A lock must minimally be a
  637. X * FileLock structure, with additional private information after the
  638. X * FileLock structure.    The longword before the beginning of the structure
  639. X * must contain the length of structure + 4.
  640. X *
  641. X * NOTE!!!!! The workbench does not follow the rules and assumes it can copy
  642. X * lock structures.  This means that if you want to be workbench
  643. X * compatible, your lock structures must be EXACTLY sizeof(struct
  644. X * FileLock). Also, it sometimes uses uninitialized values for the lock mode...
  645. X */
  646. X
  647. Xstruct FileLock *
  648. XNewFileLock(msfl, fl)
  649. Xstruct MSFileLock *msfl;
  650. Xstruct FileLock *fl;
  651. X{
  652. X    struct FileLock *newlock;
  653. X    DEVLIST *volnode;
  654. X
  655. X    if (fl) {
  656. X    volnode = BTOC(fl->fl_Volume);
  657. X    } else {
  658. X    volnode = VolNode;
  659. X    }
  660. X
  661. X    if (newlock = dosalloc((ulong)sizeof (*newlock))) {
  662. X    newlock->fl_Key = (ulong) msfl;
  663. X    newlock->fl_Task = DosPort;
  664. X    newlock->fl_Volume = (BPTR) CTOB(volnode);
  665. X    Forbid();
  666. X    newlock->fl_Link = volnode->dl_LockList;
  667. X    volnode->dl_LockList = (BPTR) CTOB(newlock);
  668. X    Permit();
  669. X    } else
  670. X    error = ERROR_NO_FREE_STORE;
  671. X
  672. X    return newlock;
  673. X}
  674. X
  675. X/*
  676. X *  This should be called before MSUnLock(), so that it may call
  677. X *  MayFreeVolNode() which then calls FreeVolNode(). A bit tricky,
  678. X *  I'm sorry for that.
  679. X */
  680. X
  681. Xlong
  682. XFreeFileLock(lock)
  683. Xstruct FileLock *lock;
  684. X{
  685. X    register struct FileLock *fl;
  686. X    register struct FileLock **flp;
  687. X    DEVLIST       *volnode;
  688. X
  689. X    volnode = (DEVLIST *)BTOC(lock->fl_Volume);
  690. X    flp = (struct FileLock **) &volnode->dl_LockList;
  691. X    for (fl = BTOC(*flp); fl && fl != lock; fl = BTOC(fl->fl_Link))
  692. X    flp = (struct FileLock **)&fl->fl_Link;
  693. X
  694. X    if (fl == lock) {
  695. X    *(BPTR *)flp = fl->fl_Link;
  696. X    dosfree(fl);
  697. X    return DOSTRUE;
  698. X    } else {
  699. X    debug(("Huh?? Could not find filelock!\n"));
  700. X    return DOSFALSE;
  701. X    }
  702. X}
  703. X
  704. X/*
  705. X * Create Volume node and add to the device list.   This will
  706. X * cause the WORKBENCH to recognize us as a disk.   If we
  707. X * don't create a Volume node, Wb will not recognize us.
  708. X * However, we are a MESSYDOS: disk, Volume node or not.
  709. X */
  710. X
  711. XDEVLIST        *
  712. XNewVolNode(name, date)
  713. Xstruct DateStamp *date;
  714. Xchar *name;
  715. X{
  716. X    DOSINFO       *di;
  717. X    register DEVLIST *volnode;
  718. X    char       *volname;        /* This is my volume name */
  719. X
  720. X    di = BTOC(((ROOTNODE *) DOSBase->dl_Root)->rn_Info);
  721. X
  722. X    if (volnode = dosalloc((ulong)sizeof (DEVLIST))) {
  723. X    if (volname = dosalloc(32L)) {
  724. X        volname[0] = strlen(name);
  725. X        strcpy(volname + 1, name);      /* Make sure \0 terminated */
  726. X
  727. X        volnode->dl_Type = DLT_VOLUME;
  728. X        volnode->dl_Task = DosPort;
  729. X        volnode->dl_DiskType = IDDiskType;
  730. X        volnode->dl_Name = CTOB(volname);
  731. X        volnode->dl_VolumeDate = *date;
  732. X        volnode->dl_MSFileLockList = NULL;
  733. X
  734. X        Forbid();
  735. X        volnode->dl_Next = di->di_DevInfo;
  736. X        di->di_DevInfo = (long) CTOB(volnode);
  737. X        Permit();
  738. X    } else {
  739. X        dosfree(volnode);
  740. X        volnode = NULL;
  741. X    }
  742. X    } else {
  743. X    error = ERROR_NO_FREE_STORE;
  744. X    }
  745. X
  746. X    return volnode;
  747. X}
  748. X
  749. X/*
  750. X *  Get the current VolNode a new name from the volume label.
  751. X */
  752. X
  753. Xvoid
  754. XNewVolNodeName()
  755. X{
  756. X    if (VolNode) {
  757. X    register char *volname = BTOC(VolNode->dl_Name);
  758. X
  759. X    strncpy(volname + 1, Disk.vollabel.de_Msd.msd_Name, 8+3);
  760. X    volname[1+8+3] = '\0';      /* Make sure \0 terminated */
  761. X    ZapSpaces(volname + 1, volname + 1 + 8+3);
  762. X    volname[0] = strlen(volname+1);
  763. X    }
  764. X}
  765. X
  766. X/*
  767. X *  Get the current VolNode a new date, from the last root directory.
  768. X */
  769. X
  770. Xvoid
  771. XNewVolNodeDate()
  772. X{
  773. X    if (VolNode) {
  774. X    ToDateStamp(&VolNode->dl_VolumeDate,
  775. X            Disk.vollabel.de_Msd.msd_Date,
  776. X            Disk.vollabel.de_Msd.msd_Time);
  777. X    }
  778. X}
  779. X
  780. X/*
  781. X * Remove Volume entry.  Since DOS uses singly linked lists, we must
  782. X * (ugg) search it manually to find the link before our Volume entry.
  783. X */
  784. X
  785. Xvoid
  786. XFreeVolNode(volnode)
  787. XDEVLIST        *volnode;
  788. X{
  789. X    DOSINFO       *di = BTOC(((ROOTNODE *) DOSBase->dl_Root)->rn_Info);
  790. X    register DEVLIST *dl;
  791. X    register void  *dlp;
  792. X
  793. X    debug(("FreeVolNode %08lx\n", volnode));
  794. X
  795. X    if (volnode == NULL)
  796. X    return;
  797. X
  798. X    dlp = &di->di_DevInfo;
  799. X    Forbid();
  800. X    for (dl = BTOC(di->di_DevInfo); dl && dl != volnode; dl = BTOC(dl->dl_Next))
  801. X    dlp = &dl->dl_Next;
  802. X    if (dl == volnode) {
  803. X    *(BPTR *) dlp = dl->dl_Next;
  804. X    dosfree(BTOC(dl->dl_Name));
  805. X    dosfree(dl);
  806. X    }
  807. X#ifdef DEBUG
  808. X    else {
  809. X    debug(("****PANIC: Unable to find volume node\n"));
  810. X    }
  811. X#endif                /* DEBUG */
  812. X    Permit();
  813. X
  814. X    if (volnode == VolNode)
  815. X    VolNode = NULL;
  816. X}
  817. X
  818. X/*
  819. X *  This is also called from the real handler when the last lock on a
  820. X *  volume is UnLock()ed, or the last file has been Close()d.
  821. X */
  822. X
  823. Xint
  824. XMayFreeVolNode(volnode)
  825. XDEVLIST *volnode;
  826. X{
  827. X    if (volnode->dl_LockList == NULL) {
  828. X    FreeVolNode(volnode);
  829. X    return 1;
  830. X    }
  831. X
  832. X    return 0;
  833. X}
  834. X
  835. X/*
  836. X *  Our disk has been removed. Save the FileLocks in the dl_LockList,
  837. X *  and let the handler save its MSFileLocks in the dl_MSFileLockList field.
  838. X *  If it has nothing to save, forget about the volume, and return
  839. X *  DOSTRUE.
  840. X *  There is one subtlety that MSDiskRemoved must know about:
  841. X *  If it MSUnLock()s the last lock on the volume, the VolNode is
  842. X *  deleted via FreeLockList().. MayFreeVolNode().. FreeVolNode().
  843. X *  But then there is no place anymore to put NULL in, so that needs
  844. X *  to be done first.
  845. X */
  846. X
  847. Xint
  848. XDiskRemoved()
  849. X{
  850. X    debug(("DiskRemoved %08lx\n", VolNode));
  851. X
  852. X    if (VolNode == NULL) {
  853. X    IDDiskType = ID_NO_DISK_PRESENT;/* really business of MSDiskRemoved */
  854. X    return DOSTRUE;
  855. X    }
  856. X
  857. X    VolNode->dl_Task = NULL;
  858. X    MSDiskRemoved(&VolNode->dl_MSFileLockList);
  859. X    if (VolNode == NULL) {  /* Could happen via MSDiskRemoved() */
  860. X    return DOSTRUE;
  861. X    }
  862. X    NewVolNodeDate();       /* Fetch new date of root directory */
  863. X    VolNode = NULL;
  864. X    return DOSFALSE;
  865. X}
  866. X
  867. X/*
  868. X *  Reconstruct everything from a Volume node
  869. X */
  870. X
  871. Xvoid
  872. XDiskInserted(volnode)
  873. Xregister DEVLIST    *volnode;
  874. X{
  875. X    debug(("DiskInserted %08lx\n", volnode));
  876. X
  877. X    VolNode = volnode;
  878. X
  879. X    if (volnode) {
  880. X    volnode->dl_Task = DosPort;
  881. X    MSDiskInserted(&volnode->dl_MSFileLockList, volnode);
  882. X    volnode->dl_MSFileLockList = NULL;
  883. X    }
  884. X}
  885. X
  886. XDEVLIST *
  887. XWhichDiskInserted()
  888. X{
  889. X    char name[34];
  890. X    struct DateStamp date;
  891. X    register DEVLIST *dl = NULL;
  892. X
  893. X    if (!Inhibited && IdentifyDisk(name, &date) == 0) {
  894. X    DOSINFO        *di = BTOC(((ROOTNODE *) DOSBase->dl_Root)->rn_Info);
  895. X    byte           *nodename;
  896. X    int        namelen = strlen(name);
  897. X
  898. X    for (dl = BTOC(di->di_DevInfo); dl; dl = BTOC(dl->dl_Next)) {
  899. X        nodename = BTOC(dl->dl_Name);
  900. X        if (nodename[0] != namelen || strncmp(nodename+1,name,namelen))
  901. X        continue;
  902. X        if (dl->dl_VolumeDate == date)  /* Non-standard! Structure compare! */
  903. X        break;
  904. X    }
  905. X
  906. X    name[31] = '\0';
  907. X    if (dl == NULL)
  908. X        dl = NewVolNode(name, &date);
  909. X    }
  910. X
  911. X    return dl;
  912. X}
  913. X
  914. Xvoid
  915. XDiskChange()
  916. X{
  917. X    debug(("DiskChange\n"));
  918. X    DiskChanged = 0;
  919. X    DiskRemoved();
  920. X    DiskInserted(WhichDiskInserted());
  921. X}
  922. X
  923. Xint
  924. XCheckRead(lock)
  925. Xstruct FileLock *lock;
  926. X{
  927. X    if (lock && BTOC(lock->fl_Volume) != VolNode)
  928. X    error = ERROR_DEVICE_NOT_MOUNTED;
  929. X    else if (IDDiskType == ID_NO_DISK_PRESENT)
  930. X    error = ERROR_NO_DISK;
  931. X    else if (IDDiskType != ID_DOS_DISK)
  932. X    error = ERROR_NOT_A_DOS_DISK;
  933. X
  934. X    return error;
  935. X}
  936. X
  937. Xint
  938. XCheckWrite(lock)
  939. Xstruct FileLock *lock;
  940. X{
  941. X    if (lock && BTOC(lock->fl_Volume) != VolNode)
  942. X    error = ERROR_DEVICE_NOT_MOUNTED;
  943. X    else if (IDDiskType == ID_NO_DISK_PRESENT)
  944. X    error = ERROR_NO_DISK;
  945. X    else if (IDDiskType != ID_DOS_DISK)
  946. X    error = ERROR_NOT_A_DOS_DISK;
  947. X    else if (IDDiskState == ID_VALIDATING)
  948. X    error = ERROR_DISK_NOT_VALIDATED;
  949. X    else if (IDDiskState != ID_VALIDATED)
  950. X    error = ERROR_DISK_WRITE_PROTECTED;
  951. X
  952. X    return error;
  953. X}
  954. X
  955. X#ifdef DEBUG
  956. X            /*    DEBUGGING            */
  957. XPORT *Dbport;        /*    owned by the debug process    */
  958. XPORT *Dback;        /*    owned by the DOS device driver    */
  959. Xshort DBEnable;
  960. X
  961. X/*
  962. X *  DEBUGGING CODE.    You cannot make DOS library calls that access other
  963. X *  devices from within a DOS device driver because they use the same
  964. X *  message port as the driver.  If you need to make such calls you must
  965. X *  create a port and construct the DOS messages yourself.  I do not
  966. X *  do this.  To get debugging info out another PROCESS is created to which
  967. X *  debugging messages can be sent.
  968. X */
  969. X
  970. Xextern void debugproc();
  971. X
  972. Xdbinit()
  973. X{
  974. X    TASK *task = FindTask(NULL);
  975. X
  976. X    Dback = CreatePort("MSH:Dback", -1L);
  977. X    CreateProc("MSH_DB", (long)task->tc_Node.ln_Pri+1, CTOB(debugproc), 4096L);
  978. X    WaitPort(Dback);                                /* handshake startup    */
  979. X    GetMsg(Dback);                                  /* remove dummy msg     */
  980. X    DBEnable = 1;
  981. X    dbprintf("Debugger running V1.10\n");
  982. X}
  983. X
  984. Xdbuninit()
  985. X{
  986. X    MSG killmsg;
  987. X
  988. X    if (Dbport) {
  989. X    killmsg.mn_Length = 0;        /*    0 means die        */
  990. X    PutMsg(Dbport,  &killmsg);
  991. X    WaitPort(Dback);            /*  He's dead jim!      */
  992. X    GetMsg(Dback);
  993. X    DeletePort(Dback);
  994. X
  995. X    /*
  996. X     *  Since the debug process is running at a greater priority, I
  997. X     *  am pretty sure that it is guarenteed to be completely removed
  998. X     *  before this task gets control again.  Still, it doesn't hurt...
  999. X     */
  1000. X
  1001. X    Delay(50L);                 /*  ensure he's dead    */
  1002. X    }
  1003. X}
  1004. X
  1005. Xdbprintf(a,b,c,d,e,f,g,h,i,j)
  1006. Xlong a,b,c,d,e,f,g,h,i,j;
  1007. X{
  1008. X    struct {
  1009. X    MSG    msg;
  1010. X    char    buf[256];
  1011. X    } msgbuf;
  1012. X    register MSG *msg = &msgbuf.msg;
  1013. X    register long len;
  1014. X
  1015. X    if (Dbport && DBEnable) {
  1016. X    sprintf(msgbuf.buf,a,b,c,d,e,f,g,h,i,j);
  1017. X    len = strlen(msgbuf.buf)+1;
  1018. X    msg->mn_Length = len;    /*  Length NEVER 0  */
  1019. X    PutMsg(Dbport, msg);
  1020. X    WaitPort(Dback);
  1021. X    GetMsg(Dback);
  1022. X    }
  1023. X}
  1024. X
  1025. X/*
  1026. X *  BTW, the DOS library used by debugmain() was actually opened by
  1027. X *  the device driver.
  1028. X */
  1029. X
  1030. Xdebugmain()
  1031. X{
  1032. X    register MSG *msg;
  1033. X    register long len;
  1034. X    register void *fh;
  1035. X    void *fh2;
  1036. X    MSG DummyMsg;
  1037. X
  1038. X    Dbport = CreatePort("MSH:Dbport", -1L);
  1039. X    fh = Open("CON:0/10/640/190/FileSystem debug", MODE_NEWFILE);
  1040. X    fh2 = Open("PAR:", MODE_OLDFILE);
  1041. X    PutMsg(Dback, &DummyMsg);
  1042. X    for (;;) {
  1043. X    WaitPort(Dbport);
  1044. X    msg = GetMsg(Dbport);
  1045. X    len = msg->mn_Length;
  1046. X    if (len == 0)
  1047. X        break;
  1048. X    --len;                /*    Fix length up    */
  1049. X    if (DBEnable & 1)
  1050. X        Write(fh, msg+1, len);
  1051. X    if (DBEnable & 2)
  1052. X        Write(fh2, msg+1, len);
  1053. X    PutMsg(Dback, msg);
  1054. X    }
  1055. X    Close(fh);
  1056. X    Close(fh2);
  1057. X    DeletePort(Dbport);
  1058. X    PutMsg(Dback, msg);             /*  Kill handshake  */
  1059. X}
  1060. X
  1061. X/*
  1062. X *  The assembly tag for the DOS process:  CNOP causes alignment problems
  1063. X *  with the Aztec assembler for some reason.  I assume then, that the
  1064. X *  alignment is unknown.  Since the BCPL conversion basically zero's the
  1065. X *  lower two bits of the address the actual code may start anywhere
  1066. X *  within 8 bytes of address (remember the first longword is a segment
  1067. X *  pointer and skipped).  Sigh....  (see CreateProc() above).
  1068. X */
  1069. X
  1070. X#asm
  1071. X    public    _debugproc
  1072. X    public    _debugmain
  1073. X
  1074. X    cseg
  1075. X_debugproc:
  1076. X    nop
  1077. X    nop
  1078. X    nop
  1079. X    nop
  1080. X    nop
  1081. X    movem.l D2-D7/A2-A6,-(sp)
  1082. X    jsr    _debugmain
  1083. X    movem.l (sp)+,D2-D7/A2-A6
  1084. X    rts
  1085. X#endasm
  1086. X
  1087. X#endif                /* DEBUG */
  1088. END_OF_FILE
  1089. if test 26316 -ne `wc -c <'src/pack.c'`; then
  1090.     echo shar: \"'src/pack.c'\" unpacked with wrong size!
  1091. fi
  1092. # end of 'src/pack.c'
  1093. fi
  1094. echo shar: End of archive 5 \(of 6\).
  1095. cp /dev/null ark5isdone
  1096. MISSING=""
  1097. for I in 1 2 3 4 5 6 ; do
  1098.     if test ! -f ark${I}isdone ; then
  1099.     MISSING="${MISSING} ${I}"
  1100.     fi
  1101. done
  1102. if test "${MISSING}" = "" ; then
  1103.     echo You have unpacked all 6 archives.
  1104.     rm -f ark[1-9]isdone
  1105. else
  1106.     echo You still need to unpack the following archives:
  1107.     echo "        " ${MISSING}
  1108. fi
  1109. ##  End of shell archive.
  1110. exit 0
  1111. -- 
  1112. Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
  1113. Mail comments to the moderator at <amiga-request@cs.odu.edu>.
  1114. Post requests for sources, and general discussion to comp.sys.amiga.
  1115.